﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CodonSegDP
{

   public enum NUCLEOTID { A = 0, T = 1, C = 2, G = 3 };

    public class Segment
    {
        public String Text{get; set;}
        public int CodonSize{get; set;}
        public int MinSegSize { get; set; }
        public String ArcheCodonName { get; set; }
        public int SegmentSize{ get;set;}
        int[][] SegmentNuclDistribution =null;

        public Segment(String _Text,int _codonSize,int _minSegSize)
        {
            Text = _Text;
            CodonSize = _codonSize;
            MinSegSize = _minSegSize;
            

            SegmentNuclDistribution=AllocDimensionArray(4, CodonSize);
        }
        private int[][] AllocDimensionArray(int rows, int columns)
        {

            int[][] dimensionArray = new int[rows][];
            for (int i = 0; i < rows; i++)
            {
                dimensionArray[i] = new int[columns];
            }
            SegmentSize = 0;
            return dimensionArray;
        }

       public int AddTriplets( int currentTextPosition, int numOfTriplets)
       {
          
           for (int i = 0; i < numOfTriplets;++i )
           {
               AddTripletToSegment(Text.Substring(currentTextPosition, CodonSize));
               currentTextPosition += CodonSize;
             

           }
           
           return currentTextPosition;
       }
       public void AddTripletToSegment(String triplet)
       {

           for (int index = 0; index < CodonSize; index++)
           {
               SegmentNuclDistribution[CnvtNucliotideToIndx(triplet[index])][index]++;
           }
           SegmentSize++;
       }
       public void RemoveTripletFromSegment(String triplet)
       {
           for (int index = 0; index < CodonSize; index++)
           {
               SegmentNuclDistribution[CnvtNucliotideToIndx(triplet[index])][index]--;
              
           }
           SegmentSize--;
       }
       private int CnvtNucliotideToIndx(char nucliotide)
       {
           int index = -1;
           if (Enum.IsDefined(typeof(NUCLEOTID), Convert.ToString(nucliotide).ToUpper()))
               index = (int)Enum.Parse(typeof(NUCLEOTID), Convert.ToString(nucliotide), true);

           return index;
       }
       public void ZeroSegNuclDistribution()
       {
           for (int i = 0; i < SegmentNuclDistribution.Length; ++i)
               for (int j = 0; j < SegmentNuclDistribution[i].Length; j++)
                   SegmentNuclDistribution[i][j] = 0;
           SegmentSize = 0;

       }

       public double EvaluateCostFunction()
       {
           int cost = 0;
           int[] maxNuclDist = new int[CodonSize];
           int i = 0, j = 0;
           ArcheCodonName = String.Empty;
           String nucl = String.Empty;
           //triplet size is 3
           while (i < CodonSize)
           {
               j = 0;
               while (j < 4)
               {//4-number of nucleotides
                   if (maxNuclDist[i] < SegmentNuclDistribution[j][i])
                   {
                       maxNuclDist[i] = SegmentNuclDistribution[j][i];
                       nucl = ((NUCLEOTID)j).ToString();
                   }
                   j++;
               }
               cost += maxNuclDist[i];
               ArcheCodonName += nucl;
               i++;
           }
           return (double)cost / SegmentSize;
       }
    }
}
